/**
 * Copyright ©2016 上海屹通. All rights reserved.
 *  
 * @Title: LoginListener.java
 * @Prject: BANK-PSBC-M
 * @Description: 登录监听
 * @Package: cn.com.yitong.demo.channel.http.listener
 * @author: 何启伟（hqw@yitong.com.cn）
 * @date: 2016年2月24日 上午11:08:59
 * @version: V1.0
 */
package cn.com.yitong.app.mbank.system.channel.http.listener;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.InitializingBean;

import cn.com.yitong.app.mbank.system.login.util.LoginHelper;
import cn.com.yitong.component.channel.support.listener.RequestListener;
import cn.com.yitong.framework.core.Framework;
import cn.com.yitong.framework.core.message.vo.ResponseMessageVO;
import cn.com.yitong.framework.exception.RequestException;
import cn.com.yitong.framework.logging.SysLogger;
import cn.com.yitong.framework.support.context.AresContext;

/**
 * @ClassName: LoginListener
 * @Description: 登录监听
 * @author: 何启伟（hqw@yitong.com.cn）
 * @date: 2016年2月24日 上午11:08:59
 */
public class LoginListener implements RequestListener, InitializingBean {

	/**
	 * @FieldName: logger
	 * @FieldType: SysLogger
	 * @Description: 日志
	 */
	protected final SysLogger logger = SysLogger.getLogger(this.getClass());
	
	/**
	 * @FieldName: checkLoginTimeout
	 * @FieldType: boolean
	 * @Description: 是否开启登录超时校验（默认true）
	 */
	private final boolean checkLoginTimeout = Framework.getPropertyBoolean("component.channel.http.checkLoginTimeout");
	
	/**
	 * @FieldName: allowMultipleLogin
	 * @FieldType: boolean
	 * @Description: 是否允许同一账号多处登录（默认false）
	 */
	private final boolean allowMultipleLogin = Framework.getPropertyBoolean("component.channel.http.allowMultipleLogin");
	
	/* 
	 * (non Javadoc)
	 * @Title: beforeRequest
	 * @Description: 请求前
	 * @param context
	 * @param objects
	 * @throws RequestException
	 * @see cn.com.yitong.component.channel.listener.RequestListener#beforeRequest(cn.com.yitong.framework.support.context.AresContext, java.lang.Object[])
	 */
	public void beforeRequest(AresContext context, Object... objects) throws RequestException {
		ResponseMessageVO response = context.getResponseMessage();
		HttpServletResponse httpResponse = (HttpServletResponse) objects[1];

		//登录超时校验
		if(this.checkLoginTimeout){
			//请求校验
			if(!context.isFreeRequest()){
				//它处登录
				if(this.allowMultipleLogin == false && LoginHelper.isMultipleLogin(context)){
					LoginHelper.clearSession(context);
					try {
						httpResponse.sendError(403, LoginHelper.LOGIN_LOGOUT_MESSAGE);
					}
					catch (IOException e) {
						throw new RequestException("它处登录校验，发送HTTP错误码发生异常", e);
					}
					logger.debug("用户在多处登录，自动销毁当前会话");
					response.setError("403");
					response.setMessage("用户在多处登录，自动销毁当前会话");
					response.setSuccess(false);
					return;
				}
				//登录超时
				if(LoginHelper.isTimeout(context)){
					LoginHelper.clearSession(context);
					try {
						httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, LoginHelper.LOGIN_TIMEOUT_MESSAGE);
					}
					catch (IOException e) {
						throw new RequestException("登录超时校验，发送HTTP错误码发生异常", e);
					}
					logger.debug("会话信息超时，需重新登录");
					response.setError("401");
					response.setMessage("会话信息超时，需重新登录");
					response.setSuccess(false);
					return;
				}
			}
		}
		else{
			logger.warn("服务端未开启登录超时校验，请配置请求监听器");
		}
	}

	/* 
	 * (non Javadoc)
	 * @Title: afterRequest
	 * @Description: 请求后
	 * @param context
	 * @param objects
	 * @throws RequestException
	 * @see cn.com.yitong.component.channel.listener.RequestListener#afterRequest(cn.com.yitong.framework.support.context.AresContext, java.lang.Object[])
	 */
	public void afterRequest(AresContext context, Object... objects) throws RequestException {
	}

	/* 
	 * (non Javadoc)
	 * @Title: afterPropertiesSet
	 * @Description: 检查属性注入
	 * @throws Exception
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		if(!this.checkLoginTimeout) {
			logger.warn("服务端未开启登录超时校验，请配置请求监听器");
		}
	}

}
